home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1997 August / Walnut Creek CDROM.7z / VOL_400 / 452_01 / DOCKSRC / DOCKWIN.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-04  |  35.8 KB  |  810 lines

  1. /****************************************************************************
  2.  
  3.     Module  : DockWin.c
  4.  
  5.     Version : v1.0alpha
  6.  
  7.     Date    : 20/8/93
  8.  
  9.     Changes :  20/8/93 - Changed code which distinguishes between Windows
  10.                .EXEs & DOS .EXEs to correctly choose.
  11.                20/8/93 - Added use of RePaintSlot func to individually repaint
  12.                slots.
  13.  
  14.                13/9/93 - Changed code which sets the window position when the
  15.                user starts an application which has it's window position
  16.                stored. Code now finds top parent window of currently active
  17.                window instead of currently active window.
  18.  
  19.                30/3/94 - corrected code to handle the mail box shrinking &
  20.                getting the correct size after. Tidied up the mail timer when
  21.                the app finished. Corrected a bug which allowed the right
  22.                button click to be processed whilst a slot was being dragged.
  23.  
  24. *****************************************************************************/
  25.  
  26. /****************************************************************************
  27.  
  28.     FUNCTION: DockWinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  29.  
  30.     VERSION : v1.0
  31.  
  32.     PURPOSE :
  33.  
  34.     MESSAGES:
  35.  
  36.     COMMENTS:
  37.  
  38. ****************************************************************************/
  39.  
  40.  
  41. #include <windows.h>            /* include standard windows header */
  42. #include <shellapi.h>
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include <sys\stat.h>
  46. #include <string.h>
  47. #include "freedock.h"           /* include control message definitions */
  48.  
  49. /**********************************************************
  50.     Global Data for the various system metrics we need
  51. **********************************************************/
  52. extern GLOBAL_METRICS gMetrics;
  53. extern GLOBAL_OPTIONS gOptions;
  54.  
  55. FARPROC  lpfnAboutDockDlgProc;    // Used in dockutil.c
  56.  
  57.  
  58. long FAR PASCAL DockWinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  59. {
  60.     static SLOT_ENTRY    *Slot;
  61.     static DOCK_STRUCT    Dock;
  62.     CREATESTRUCT         *create;
  63.  
  64.     PAINTSTRUCT     ps;         /* paint struct , used when painting window */
  65.     static HDC      Win_hdc, Screen_hdc;
  66.     static HCURSOR  hRemCur;
  67.     UINT            SlotHit, FileIndex, nItem, Status;
  68.     int             i, StartSlot, EndSlot;
  69.     HANDLE          hDrop;
  70.     int             SlotIndex, nDropSlot;
  71.     UINT            nNumDropped;
  72.     char            DroppedFileName[MAX_FPATH_LEN], TmpBuffer[MAX_FPATH_LEN];
  73.     char           *TmpCharPtr;
  74.     POINT           DropPoint;
  75.     char            CommandLine[MAX_CMDLINE_LEN];
  76.     static FARPROC  lpfnAppOptionsDlgProc, lpfnMainOptionsDlgProc, lpfnMailOptionsDlgProc, lpfnClockOptionsDlgProc,
  77.                     lpfnWinExitOptionsDlgProc;
  78.     static UINT     OrigSlot;
  79.     int             NewX, NewY;
  80.     static BOOL     bDragIcon, bRemoveSlot, bSlotOffDock, bSlotMove;
  81.     static HBITMAP  hbmUnderIcon, hbmNewUnderIcon, hbmTmp;
  82.     static HBITMAP  hbmOldUnderIcon, hbmOldNewUnderIcon, hbmOldTmp, hbmOldIconCache;
  83.     static HDC      hdcUnderIcon, hdcNewUnderIcon, hdcTmp;
  84.     struct stat     StatBuf;
  85.  
  86.     static int      OldLeft, OldTop, OffLeft, OffTop;  // Old coordinates and Offset coordinates
  87.     static RECT     MoveRect, Rect;
  88.     static BOOL     bDragDock;
  89.     static BOOL     bWindowPositioned = FALSE;
  90.     static HCURSOR  hCurHand, hCurOld;
  91.  
  92.     /* Select messages which are handled by this procedure */
  93.  
  94.     switch (message) {
  95.  
  96.         case WM_CREATE:             /* The window has just been created */
  97.             /********************************************************
  98.                 malloc the memory for the maximum number of slots
  99.             ********************************************************/
  100.             Slot = (SLOT_ENTRY *)calloc(gOptions.MaxDockSize, sizeof(SLOT_ENTRY));
  101.             if(Slot == NULL){
  102.                 MessageBox( NULL, "FreeDock Error",
  103.                     "Cannot allocate memory for dock slots",
  104.                     MB_ICONSTOP | MB_OK); 
  105.                 exit(-3);
  106.             }
  107.             Dock.Slot = Slot;
  108.  
  109.             /*********************************************
  110.                 No need to initialise all slot types to
  111.                 being free since SLOT_FREE is 0 and we
  112.                 used calloc to get the memory
  113.             *********************************************/
  114.             /***************************
  115.                 Read Dock Options
  116.             ***************************/
  117.             ReadDockOptions( &Dock );
  118.  
  119.             /**********************************
  120.                 Initialise Dock Window var 
  121.             **********************************/
  122.             Dock.hwndDock = hwnd;
  123.  
  124.             /*******************************
  125.                 Is this the Root Dock ?
  126.             *******************************/
  127.             create = (CREATESTRUCT *)lParam;
  128.             if( create->hwndParent == NULL ){
  129.                 Dock.DockType = ROOT_DOCK;
  130.             }
  131.             else{
  132.                 Dock.DockType = SUB_DOCK;
  133.             }
  134.  
  135.            /**********************************************************************
  136.                 Create bitmaps and device contexts for the icon cache Item at end
  137.                 of cache is for TmpSlot/Icons scratch space
  138.                 These are always the default (correct) slot width and height so
  139.                 that the slot icons & buttons are stored at 1:1 and then scaled
  140.                 when painted on the dock
  141.             **********************************************************************/
  142.             Win_hdc = GetDC(hwnd);
  143.             Dock.hbmIconCache = CreateCompatibleBitmap( Win_hdc,  DEF_SLOT_WIDTH * (gOptions.MaxDockSize+1), DEF_SLOT_HEIGHT );
  144.             Dock.hdcIconCache = CreateCompatibleDC(Win_hdc);
  145.             hbmOldIconCache = SelectObject(Dock.hdcIconCache, Dock.hbmIconCache);
  146.             ReleaseDC( hwnd, Win_hdc );
  147.             /**********************************************************            
  148.                 Initialise each Slots Icon position within the cache
  149.                 and the pointer to the parent Dock
  150.             **********************************************************/                                                                       
  151.             for( i=0; i < gOptions.MaxDockSize; i++ ){
  152.                  Slot[i].IconIndex = i * DEF_SLOT_WIDTH;
  153.                 Slot[i].Dock = &Dock;
  154.             }                                                                       
  155.             
  156.             /**************************
  157.                 Read in all slot info
  158.             **************************/
  159.  
  160.             ReadAllSlotOptions(&Dock, Slot);
  161.  
  162.             /*****************************************************
  163.                 Limit Dock Size to max value set in .INI file
  164.             *****************************************************/
  165.             Dock.SlotCount = (Dock.SlotCount < gOptions.MaxDockSize)?Dock.SlotCount:gOptions.MaxDockSize;
  166.  
  167.             /****************************************************
  168.                 Create a bitmap to store what is under the icon
  169.                 when moving a slot, + A scratch pad of the same
  170.                 size. (Tmp)
  171.             ****************************************************/
  172.             Win_hdc = GetDC(hwnd);
  173.             hbmUnderIcon = CreateCompatibleBitmap( Win_hdc,
  174.                                                    MAX_SLOT_WIDTH,
  175.                                                    MAX_SLOT_HEIGHT );
  176.             hbmNewUnderIcon = CreateCompatibleBitmap( Win_hdc,
  177.                                                       MAX_SLOT_WIDTH,
  178.                                                       MAX_SLOT_HEIGHT );
  179.             hbmTmp = CreateCompatibleBitmap( Win_hdc,
  180.                                              MAX_SLOT_WIDTH,
  181.                                              MAX_SLOT_HEIGHT );
  182.             hdcUnderIcon    = CreateCompatibleDC(Win_hdc);
  183.             hdcNewUnderIcon = CreateCompatibleDC(Win_hdc);
  184.             hdcTmp          = CreateCompatibleDC(Win_hdc);
  185.             ReleaseDC(hwnd, Win_hdc);
  186.  
  187.             hbmOldUnderIcon    = SelectObject(hdcUnderIcon,    hbmUnderIcon);
  188.             hbmOldNewUnderIcon = SelectObject(hdcNewUnderIcon, hbmNewUnderIcon);
  189.             hbmOldTmp          = SelectObject(hdcTmp,          hbmTmp);
  190.  
  191.             hCurHand = LoadCursor(gOptions.hAppInst, "Hand");
  192.  
  193.             /******************************************************
  194.                 Identify this window as a drag and drop acceptor
  195.             ******************************************************/
  196.             DragAcceptFiles(hwnd, TRUE);
  197.  
  198.             bDragIcon = FALSE;
  199.             bDragDock = FALSE;
  200.             /**************************************************
  201.             * Create all proc instances for all dialog boxes *
  202.             **************************************************/
  203.             lpfnAppOptionsDlgProc = MakeProcInstance((FARPROC) AppOptionsDlgProc, gOptions.hAppInst);
  204.             lpfnWinExitOptionsDlgProc = MakeProcInstance((FARPROC) WinExitOptionsDlgProc, gOptions.hAppInst);
  205.             lpfnMailOptionsDlgProc = MakeProcInstance((FARPROC) MailOptionsDlgProc, gOptions.hAppInst);
  206.             lpfnMainOptionsDlgProc = MakeProcInstance((FARPROC) MainOptionsDlgProc, gOptions.hAppInst);
  207.             lpfnClockOptionsDlgProc = MakeProcInstance((FARPROC) ClockOptionsDlgProc, gOptions.hAppInst);
  208.             lpfnAboutDockDlgProc = MakeProcInstance((FARPROC) AboutDockDlgProc, gOptions.hAppInst);
  209.  
  210.             if (gOptions.AlwaysOnTop) {
  211.                 SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  212.             }
  213.             if (gOptions.MailActive) {
  214.                 SetTimer(hwnd, MAIL_TIMER, gOptions.MailFreq * 1000 * 60, NULL);
  215.             }
  216.             return 0;               /* end of WM_CREATE */
  217.  
  218.  
  219.         case WM_PAINT:
  220.             /** Make sure the dock is in the correct position **/
  221.             /** Cannot do this from WM_CREATE Message         **/
  222.             if( !bWindowPositioned ){
  223.                 SetDockWinPos( &Dock, Dock.Orientation + QX_HORZ );
  224.                 bWindowPositioned = TRUE;
  225.             }
  226.  
  227.             Win_hdc = BeginPaint(hwnd, &ps);
  228.             StartSlot = FindSlotHit(Dock.Orientation, ps.rcPaint.left, ps.rcPaint.top);
  229.             EndSlot = FindSlotHit(Dock.Orientation, ps.rcPaint.right, ps.rcPaint.bottom);
  230.  
  231.             for (i = StartSlot; i <= EndSlot; i++) {
  232.                 PaintSlot(Win_hdc, &Dock, &Slot[i]);
  233.             }
  234.             EndPaint(hwnd, &ps);
  235.             return 0;
  236.  
  237.  
  238.         case WM_TIMER:
  239.             if(Dock.DockType != ROOT_DOCK) return 0;
  240.             if (wParam == MAIL_TIMER) {
  241.                 stat(gOptions.MailPath, &StatBuf);
  242.                 if (StatBuf.st_size > gOptions.MailBoxSize) {
  243.                     gOptions.MailBoxSize = (unsigned long) StatBuf.st_size;
  244.                     i = 0;
  245.                     while ((Slot[i].SlotType != SLOT_SPECIAL_MAIL) && (i < 4))
  246.                         i++;
  247.                     if (Slot[i].SlotType != SLOT_SPECIAL_MAIL){
  248.                         KillTimer(hwnd, MAIL_TIMER);
  249.                         return 0;
  250.                     }
  251.                     gOptions.bMailInBox = TRUE;
  252.                     UtilLoadIcon( &Dock, &Slot[i] );
  253.                     if (gOptions.MailSound) {
  254.                         MessageBeep(MB_ICONHAND);
  255.                     }
  256.                     RePaintSlot(&Dock, &Slot[i], FALSE);
  257.                 } 
  258.                 else if (StatBuf.st_size < gOptions.MailBoxSize) {
  259.                     gOptions.MailBoxSize = (unsigned long) StatBuf.st_size;
  260.                 }
  261.             }
  262.             return 0;
  263.  
  264.         case WM_LBUTTONDOWN:
  265.             SetCapture(hwnd);
  266.             OldLeft = LOWORD(lParam);
  267.             OldTop = HIWORD(lParam);
  268.             OrigSlot = FindSlotHit(Dock.Orientation, OldLeft, OldTop);
  269.             if( Slot[OrigSlot].SlotType == SLOT_USED ){
  270.                 if(!gOptions.DockLocked) hCurOld = SetCursor(hCurHand);
  271.  
  272.                 /***********************************************************
  273.                     Delete slot temporaraly & FORCE a repaint before
  274.                     going any further.
  275.                 ***********************************************************/
  276.                 Slot[OrigSlot].SlotType = SLOT_FREE;
  277.                 bDragIcon = TRUE;
  278.                 bSlotMove = FALSE;
  279.                 bRemoveSlot = FALSE;
  280.                 bDragDock = FALSE;
  281.             }
  282.             else if(Slot[OrigSlot].SlotType == SLOT_SPECIAL_TITLE){
  283.                 Screen_hdc = GetDC(NULL);
  284.                 bDragDock = TRUE;
  285.                 bDragIcon = FALSE;
  286.                 OffLeft = OldLeft; // Save offset of mouse
  287.                 OffTop = OldTop; // from top left of rect
  288.                 MoveRect.left   = Dock.DockLeft;
  289.                 MoveRect.top    = Dock.DockTop;
  290.                 if(Dock.Orientation == DOCK_HORZ){
  291.                     MoveRect.bottom = MoveRect.top + gOptions.SlotHeight;
  292.                     MoveRect.right  = MoveRect.left + Dock.SlotCount*gOptions.SlotHeight;
  293.                 }
  294.                 else{
  295.                     MoveRect.bottom = MoveRect.top + Dock.SlotCount*gOptions.SlotHeight;
  296.                     MoveRect.right  = MoveRect.left + gOptions.SlotWidth;
  297.                 }
  298.                 DrawFocusRect( Screen_hdc, &MoveRect );
  299.             }
  300.             else{
  301.                 bDragDock = FALSE;
  302.                 bDragIcon = FALSE;
  303.                 bRemoveSlot = FALSE;
  304.             }
  305.             return 0;
  306.  
  307.         case WM_LBUTTONUP:
  308.             ReleaseCapture();
  309.             if (bDragDock){
  310.                 DrawFocusRect( Screen_hdc, &MoveRect ); // Erase old frame
  311.                 bDragDock = FALSE;
  312.  
  313.                 Dock.DockLeft += ((short int)LOWORD(lParam) - OffLeft);
  314.                 Dock.DockTop += ((short int)HIWORD(lParam) - OffTop);
  315.                 SetDockWinPos( &Dock, Dock.Orientation + QX_HORZ ); // Move Dock to new position
  316.  
  317.                 ReleaseDC(NULL, Screen_hdc);
  318.                 WriteDockOptions( &Dock );    // Update Position entry in ini file
  319.             }
  320.             else if( bDragIcon ){
  321.                 if(!gOptions.DockLocked) SetCursor(hCurOld);
  322.  
  323.                 if(bSlotMove){
  324.                     Win_hdc = GetDC(hwnd);
  325.                     BitBlt( Win_hdc, OldLeft-(gOptions.SlotWidth/2), OldTop-(gOptions.SlotHeight/2), 
  326.                             gOptions.SlotWidth, gOptions.SlotHeight, hdcUnderIcon, 0, 0, SRCCOPY);
  327.                     ReleaseDC(hwnd, Win_hdc);
  328.                 }
  329.  
  330.                 // Reset Slot status flag to true state;
  331.                 Slot[OrigSlot].SlotType = SLOT_USED;
  332.                 // Find the slot hit when the button was released, if the dock is locked
  333.                 // fake this by setting the hit slot to the original slot
  334.                 if( gOptions.DockLocked ){
  335.                     SlotHit = OrigSlot;
  336.                 }
  337.                 else{
  338.                     SlotHit = FindSlotHit(Dock.Orientation, LOWORD(lParam), HIWORD(lParam));
  339.                 }
  340.  
  341.                 if(bRemoveSlot){
  342.                     UtilEmptySlot( &Slot[OrigSlot] );
  343.                     WriteSlotOptions( &Dock, &Slot[OrigSlot] );    // Delete entry in ini file
  344.                     if(bSlotMove)
  345.                         RePaintSlot(&Dock, &Slot[OrigSlot], TRUE);
  346.                 }
  347.                 else if (SlotHit != OrigSlot){   // if the slot actually moved
  348.  
  349.                     if( (Slot[SlotHit].SlotType == SLOT_USED) ||
  350.                         (Slot[SlotHit].SlotType == SLOT_FREE)){
  351.  
  352.                         SwapSlots( &Slot[OrigSlot], &Slot[SlotHit] );
  353.  
  354.                         if(bSlotMove)
  355.                             RePaintSlot( &Dock, &Slot[OrigSlot], FALSE );
  356.                     }
  357.                     else {   // Slot must be a special, can't move a slot to here.
  358.                         if(bSlotMove)
  359.                             RePaintSlot( &Dock, &Slot[OrigSlot], FALSE );
  360.                     }
  361.  
  362.                     WriteSlotOptions( &Dock, &Slot[SlotHit] );    // Update entry in ini file
  363.                     WriteSlotOptions( &Dock, &Slot[OrigSlot] );    // Update entry in ini file
  364.                 }
  365.                 else{
  366.                     RePaintSlot( &Dock, &Slot[SlotHit], FALSE );
  367.                 }
  368.  
  369.                 if(bSlotMove){
  370.                     RePaintSlot(&Dock, &Slot[SlotHit-1], TRUE);
  371.                     RePaintSlot(&Dock, &Slot[SlotHit]  , TRUE);
  372.                     RePaintSlot(&Dock, &Slot[SlotHit+1], TRUE);
  373.                 }
  374.                 else{
  375.                     /*******************************************
  376.                         Slot did not move, so treat this
  377.                         as a single left click message &
  378.                         run the app, if SingleClickStart
  379.                         is TRUE
  380.                     *******************************************/
  381.                     if( gOptions.SingleClickStart ){
  382.                         SendMessage( hwnd, WM_LBUTTONDBLCLK, wParam, lParam );
  383.                     }
  384.                 }
  385.                 bDragIcon = FALSE;
  386.             }
  387.             return 0;
  388.  
  389.         case WM_MOUSEMOVE:
  390.             if (bDragDock){
  391.                 DrawFocusRect( Screen_hdc, &MoveRect ); // Erase old frame
  392.                 OldLeft = (short int)LOWORD(lParam);
  393.                 OldTop  = (short int)HIWORD(lParam);
  394.                 MoveRect.left   = (Dock.DockLeft + OldLeft) - OffLeft;
  395.                 MoveRect.top    = (Dock.DockTop + OldTop) - OffTop;
  396.  
  397.                 if(Dock.Orientation == DOCK_HORZ){
  398.                     MoveRect.bottom = MoveRect.top + gOptions.SlotHeight;
  399.                     MoveRect.right  = MoveRect.left + Dock.SlotCount*gOptions.SlotHeight;
  400.                 }
  401.                 else{
  402.                     MoveRect.bottom = MoveRect.top + Dock.SlotCount*gOptions.SlotHeight;
  403.                     MoveRect.right  = MoveRect.left + gOptions.SlotWidth;
  404.                 }
  405.                 DrawFocusRect( Screen_hdc, &MoveRect );
  406.             }
  407.             else if(bDragIcon && !gOptions.DockLocked){ //:-)
  408.                 if( IsCursorOutOfDock( &Dock, (int)LOWORD(lParam), (int)HIWORD(lParam)) ){
  409.                     if(!bRemoveSlot){
  410.                         bSlotOffDock = FALSE;
  411.                         bRemoveSlot = TRUE;
  412.                         hRemCur = LoadCursor(gOptions.hAppInst, "RemoveSlot");
  413.                         SetCursor( hRemCur );
  414.                     }
  415.                     if(bSlotOffDock) return(TRUE);
  416.                 }
  417.                 else if(bRemoveSlot){
  418.                     bRemoveSlot = FALSE;
  419.                     SetCursor(hCurHand);
  420.                     DestroyCursor(hRemCur);
  421.                 }
  422.  
  423.                 if( !bSlotMove ){
  424.                     Win_hdc = GetDC(hwnd);
  425.  
  426.                     /******************************************
  427.                          Paint the area under the blank slot
  428.                     ******************************************/
  429.                     BlankSlot( Win_hdc, &Dock,  &Slot[OrigSlot] );
  430.  
  431.                     /*****************************************
  432.                     Copy what will be under the Icon
  433.                     *****************************************/
  434.                     BitBlt( hdcUnderIcon, 0, 0, gOptions.SlotWidth, gOptions.SlotHeight,
  435.                             Win_hdc, OldLeft-(gOptions.SlotWidth/2), OldTop-(gOptions.SlotHeight/2), SRCCOPY);
  436.                     /********************
  437.                         Draw the Icon
  438.                     ********************/
  439.                     UtilDrawIcon( Win_hdc, &Dock, &Slot[OrigSlot], OldLeft-(gOptions.SlotWidth/2), 
  440.                                   OldTop-(gOptions.SlotHeight/2), TRUE);
  441.  
  442.                     ReleaseDC(hwnd, Win_hdc);
  443.                     bSlotMove = TRUE;
  444.                     bDragIcon = TRUE;
  445.                     return(TRUE);
  446.                 }
  447.  
  448.                 /*****************************************************************
  449.                     The following is an attempt at getting flicker free dragging
  450.                     of a slot around the dock, third buffer required to eliminate
  451.                     trailing/leading edge flicker when dragging
  452.                 *****************************************************************/
  453.                 NewX = LOWORD(lParam);
  454.                 NewY = HIWORD(lParam);
  455.                 Win_hdc = GetDC(hwnd);
  456.                 // Blit what will be covered to Tmp
  457.                 BitBlt( hdcNewUnderIcon, 0, 0, gOptions.SlotWidth, gOptions.SlotHeight,
  458.                         Win_hdc, NewX-(gOptions.SlotWidth/2), NewY-(gOptions.SlotHeight/2), SRCCOPY);
  459.  
  460.                 // Blit UnderIcon to old-new in tmp
  461.                 BitBlt( hdcNewUnderIcon, (OldLeft)-NewX, (OldTop)-NewY, gOptions.SlotWidth, gOptions.SlotHeight,
  462.                         hdcUnderIcon, 0, 0, SRCCOPY);
  463.  
  464.                 // Draw complete Icon into buffer & then blit to screen
  465.                 UtilDrawIcon( hdcTmp, &Dock, &Slot[OrigSlot], 0, 0, TRUE );
  466.  
  467.                 // Draw Icon into Under Icon Bmp at new-old
  468.                 UtilDrawIcon( hdcUnderIcon, &Dock, &Slot[OrigSlot], NewX-(OldLeft), NewY-(OldTop), TRUE);
  469.  
  470.                 // Blit complete icon to screen
  471.                 BitBlt( Win_hdc, NewX-(gOptions.SlotWidth/2), NewY-(gOptions.SlotHeight/2), 
  472.                         gOptions.SlotWidth, gOptions.SlotHeight, hdcTmp, 0, 0, SRCCOPY);
  473.  
  474.                 // Replace what was covered by the icon, and is not covered by new pos
  475.                 BitBlt( Win_hdc, (OldLeft-(gOptions.SlotWidth/2)), (OldTop-(gOptions.SlotHeight/2)), 
  476.                         gOptions.SlotWidth, gOptions.SlotHeight, hdcUnderIcon, 0, 0, SRCCOPY);
  477.  
  478.                 // Save new image of what's under the icon.
  479.                 BitBlt( hdcUnderIcon, 0, 0, gOptions.SlotWidth, gOptions.SlotHeight,
  480.                         hdcNewUnderIcon, 0, 0, SRCCOPY);
  481.  
  482.                 // Save new posn
  483.                 OldLeft = NewX;
  484.                 OldTop = NewY;
  485.  
  486.                 if(!bSlotOffDock) bSlotOffDock = TRUE;
  487.                 ReleaseDC(hwnd, Win_hdc);
  488.             }
  489.             return 0;
  490.  
  491.  
  492.         case WM_LBUTTONDBLCLK:
  493.             /*******************************************************************
  494.                First need to calculate which button has been hit, by dividing
  495.                the y coordinate by the height of the buttons and subtracting
  496.                the number of special buttons operational and 1 for the title
  497.                Icon.
  498.             *******************************************************************/
  499.  
  500.             SlotHit = FindSlotHit(Dock.Orientation, LOWORD(lParam), HIWORD(lParam));
  501.  
  502.             switch (Slot[SlotHit].SlotType) {
  503.                 case SLOT_USED:
  504.                     RePaintSlot( &Dock, &Slot[SlotHit], FALSE);
  505.                     ExecSlot( &Slot[SlotHit], Slot[SlotHit].CmdLine );
  506.                     break;
  507.  
  508.                 case SLOT_SPECIAL_MAIL:
  509.                     gOptions.bMailInBox = FALSE;
  510.                     UtilLoadIcon( &Dock, &Slot[SlotHit] );
  511.                     RePaintSlot(&Dock, &Slot[SlotHit], FALSE);
  512.                     break;
  513.  
  514.                 case SLOT_SPECIAL_EXIT:
  515.                     if (gOptions.WinExitConfirm) {
  516.                         nItem = MessageBox(hwnd, "Do you really want to exit Windows ?",
  517.                             "FreeDock", MB_OKCANCEL | MB_ICONSTOP);
  518.                         if (nItem == IDOK) {
  519.                             ExitWindows(0, 0);
  520.                         }
  521.                     } 
  522.                     else {
  523.                         ExitWindows(0, 0);
  524.                     }
  525.                     break;
  526.  
  527.                 case SLOT_SPECIAL_TITLE:
  528.                     DialogBox(gOptions.hAppInst, "ABOUTDOCKDLG", hwnd, lpfnAboutDockDlgProc);
  529.                     break;
  530.  
  531.             }
  532.             return 0;
  533.  
  534.         case WM_DROPFILES:
  535.             hDrop = (HANDLE)wParam;
  536.  
  537.             /***********************************************************
  538.                Find out if the drop point was in the client area.
  539.                This must be the case, or an error has occurred.
  540.             ***********************************************************/
  541.             if( ! DragQueryPoint(hDrop, (LPPOINT)&DropPoint) ){
  542.                 sprintf(TmpBuffer, "Error Occurred : DockWinProc()\n(WM_DROPFILES, Drop point not in client area).");
  543.                 MessageBox(hwnd, TmpBuffer, "FreeDock", MB_OK | MB_ICONSTOP);
  544.                 break;
  545.             }
  546.  
  547.             /*******************************************
  548.                 Find out how many files were dropped
  549.             *******************************************/
  550.             nNumDropped = DragQueryFile(hDrop, -1, (LPSTR)NULL, 0);
  551.  
  552.             if( nNumDropped < 1 ){
  553.                 sprintf(TmpBuffer, "Error Occurred : DockWinProc()\n(WM_DROPFILES, DragQuery returned %d).", nNumDropped);
  554.                 MessageBox(hwnd, TmpBuffer, "FreeDock", MB_OK | MB_ICONSTOP);
  555.                 break;
  556.             }
  557.  
  558.             SlotHit = FindSlotHit(Dock.Orientation, DropPoint.x, DropPoint.y);
  559.  
  560.             switch (Slot[SlotHit].SlotType) {
  561.  
  562.                 case SLOT_USED:
  563.                     /***********************************************************
  564.                         Build up the command line and then call the ExecSlot
  565.                         function to execute the associated program
  566.                     ***********************************************************/
  567.                     sprintf(CommandLine, "%s ", Slot[SlotHit].CmdLine);
  568.                     for (FileIndex = 0; FileIndex < nNumDropped; FileIndex++) {
  569.                         DragQueryFile(hDrop, FileIndex, DroppedFileName, MAX_FPATH_LEN);
  570.                         /************************************************
  571.                             Check if this file has an extension, if not
  572.                             add a trailing '.'
  573.                         ************************************************/
  574.                         if (!strchr(&DroppedFileName[strlen(DroppedFileName) - 4], '.')) {
  575.                             DroppedFileName[strlen(DroppedFileName) + 1] = '\0';
  576.                             DroppedFileName[strlen(DroppedFileName)] = '.';
  577.                         }
  578.  
  579.                         // Add Filename to Commandline if it will fit
  580.                         if( (strlen(CommandLine) + strlen(DroppedFileName)+1) < MAX_CMDLINE_LEN ) {
  581.                             strcat(CommandLine, DroppedFileName);
  582.                             strcat(CommandLine, " ");
  583.                         }
  584.                         else{
  585.                             MessageBox(hwnd, "Too many files dropped to fit on application command line, ignoring extras.",
  586.                                         "FreeDock Error", MB_OK | MB_ICONSTOP);
  587.                              break;
  588.                         }
  589.                     }
  590.  
  591.                     ExecSlot( &Slot[SlotHit], CommandLine );
  592.  
  593.                     break;
  594.  
  595.                 case SLOT_FREE:
  596.                     nDropSlot = SlotHit;
  597.                     SlotIndex = SlotHit;
  598.                     for (FileIndex = 0; FileIndex < nNumDropped; FileIndex++) {
  599.                         DragQueryFile(hDrop, FileIndex, DroppedFileName, MAX_FPATH_LEN);
  600.                         Slot[SlotIndex].SlotType = SLOT_USED;
  601.                         Slot[SlotIndex].StartState = START_NORMAL;
  602.                         Slot[SlotIndex].WinX = DEF_STORE_X;
  603.                         Slot[SlotIndex].WinY = DEF_STORE_Y;
  604.                         Slot[SlotIndex].WinWidth = DEF_STORE_W;
  605.                         Slot[SlotIndex].WinHeight = DEF_STORE_H;
  606.                         strcpy(Slot[SlotIndex].AppName, DroppedFileName);
  607.                         strcpy(Slot[SlotIndex].RunTimeDir, DroppedFileName);
  608.                         strcpy(Slot[SlotIndex].IconFile, DroppedFileName);
  609.                         Slot[SlotIndex].IconPos = 0;
  610.  
  611.                         /************************************************
  612.                            Set Run Time Dir to be same path as filename
  613.                         ************************************************/
  614.                         TmpCharPtr = strrchr(Slot[SlotIndex].RunTimeDir, '\\');
  615.                         if (*(TmpCharPtr-1) == ':')
  616.                             *(TmpCharPtr+1) = '\0';
  617.                         else
  618.                             *TmpCharPtr = '\0';
  619.  
  620.                         /*****************************************************************
  621.                            Check What type of file has been dropped, is it a .PIF, .COM
  622.                            or a .BAT ?
  623.                         *****************************************************************/
  624.                         if (!stricmp(&DroppedFileName[strlen(DroppedFileName) - 4], ".PIF") ||
  625.                             !stricmp(&DroppedFileName[strlen(DroppedFileName) - 4], ".COM") ||
  626.                             !stricmp(&DroppedFileName[strlen(DroppedFileName) - 4], ".BAT")) {
  627.  
  628.  
  629.                             Status = (UINT)FindExecutable("progman.exe",
  630.                                                           NULL,
  631.                                                           Slot[SlotIndex].IconFile);
  632.                             if( Status <= 31 ){
  633.                                     MessageBox(hwnd, "Program Manager not found, cannot select default Icon.",
  634.                                                "FreeDock Error", MB_OK | MB_ICONSTOP);
  635.                             }
  636.                             Slot[SlotIndex].IconPos = 1;
  637.                             // Load the Icon into the slot's own bitmap
  638.                             UtilLoadIcon( &Dock, &Slot[SlotIndex] );
  639.                         }
  640.                         /******************************************************************
  641.                             Is is a .EXE, if so is it a Windows EXE or a DOS EXE ?
  642.                         ******************************************************************/
  643.                         else if (!stricmp(&DroppedFileName[strlen(DroppedFileName) - 4], ".EXE")) {
  644.                             // Load the Icon into the slot's own bitmap
  645.                             UtilLoadIcon( &Dock, &Slot[SlotIndex] );
  646.                             if (Slot[SlotIndex].IconTotal == 0) {
  647.  
  648.                                 Status = (UINT)FindExecutable("progman.exe",
  649.                                                               NULL,
  650.                                                               Slot[SlotIndex].IconFile);
  651.                                 if( Status <= 31 ){
  652.                                         MessageBox(hwnd, "Program Manager not found, cannot select default Icon.",
  653.                                                    "FreeDock Error", MB_OK | MB_ICONSTOP);
  654.                                 }
  655.  
  656.                                 Slot[SlotIndex].IconPos = 1;
  657.                                 // Load the Icon into the slot's own bitmap
  658.                                 UtilLoadIcon( &Dock, &Slot[SlotIndex] );
  659.  
  660.                             }
  661.                         }
  662.                         /******************************************************************
  663.                             It must be a document file, try to find an association for it
  664.                         ******************************************************************/
  665.                         else {
  666.                             strcpy(Slot[SlotIndex].CmdLine, Slot[SlotIndex].AppName);
  667.                             // Read the executable name in,
  668.                             // then call SearchPath to get entire path for application.
  669.                             Status = (UINT)FindExecutable(Slot[SlotIndex].CmdLine,
  670.                                 Slot[SlotIndex].RunTimeDir,
  671.                                 Slot[SlotIndex].AppName);
  672.                                 
  673.                             // Now call find executable to ensure we have a complete
  674.                             // path to the application
  675.                             if( FindExecutable(Slot[SlotIndex].AppName,
  676.                                 Slot[SlotIndex].RunTimeDir,
  677.                                 TmpBuffer) > (HINSTANCE)32 ){
  678.                                   strcpy( Slot[SlotIndex].AppName, TmpBuffer);
  679.                             }
  680.                             
  681.                             if (Status > 32) {
  682.                                 strcpy(Slot[SlotIndex].IconFile, Slot[SlotIndex].AppName);
  683.                                 Slot[SlotIndex].IconPos = 0;
  684.                                 // Load the Icon into the slot's own bitmap
  685.                                 UtilLoadIcon( &Dock, &Slot[SlotIndex] );
  686.                             } 
  687.                             else {
  688.                                 sprintf(TmpBuffer, "%s\nis not an executable or an associated file", Slot[SlotIndex].CmdLine);
  689.                                 MessageBox(hwnd, TmpBuffer, "FreeDock", MB_OK | MB_ICONSTOP);
  690.                                 Slot[SlotIndex].SlotType = SLOT_FREE;
  691.                             }
  692.                         }
  693.  
  694.                         RePaintSlot(&Dock, &Slot[SlotIndex], FALSE);
  695.  
  696.                         WriteSlotOptions(&Dock, &Slot[SlotIndex]);    // Save the new slot
  697.  
  698.                         SlotIndex++;
  699.                         while ((SlotIndex != nDropSlot) && (Slot[SlotIndex].SlotType != SLOT_FREE)) {
  700.                             SlotIndex++;
  701.                             if (SlotIndex >= Dock.SlotCount)
  702.                                 SlotIndex = 1;
  703.                         }
  704.                         if (SlotIndex == nDropSlot)
  705.                             break;
  706.                     }
  707.                     break;
  708.  
  709.             }
  710.  
  711.             DragFinish(hDrop);
  712.  
  713.             return 0;
  714.  
  715.         case WM_RBUTTONDOWN:
  716.             /**********************************************************
  717.               If we are currently dragging a slot or the dock  around
  718.               then ignore any buttons being pressed
  719.           ************************************************************/
  720.             if( bDragIcon || bDragDock ) return 0;
  721.  
  722.             SlotHit = FindSlotHit(Dock.Orientation, LOWORD(lParam), HIWORD(lParam));
  723.  
  724.             switch (Slot[SlotHit].SlotType) {
  725.                 case SLOT_USED:
  726.                 case SLOT_FREE:
  727.                     Status = DialogBoxParam( gOptions.hAppInst, "APPOPTIONSDLG", hwnd, 
  728.                                             lpfnAppOptionsDlgProc, (LPARAM)&Slot[SlotHit] );
  729.                     if(Status) WriteSlotOptions(&Dock, &Slot[SlotHit]);
  730.                     break;
  731.  
  732.                 case SLOT_SPECIAL_TITLE:
  733.                     Status = DialogBoxParam( gOptions.hAppInst, "MAINOPTIONSDLG", hwnd, 
  734.                                              lpfnMainOptionsDlgProc, (LPARAM)&Dock);
  735.                     if(Status){
  736.                         WriteGlobalOptions();
  737.                         WriteDockOptions( &Dock );
  738.                     }
  739.                     break;
  740.  
  741.                 case SLOT_SPECIAL_EXIT:
  742.                     Status = DialogBox(gOptions.hAppInst, "WINEXITOPTIONSDLG", hwnd, lpfnWinExitOptionsDlgProc);
  743.                     if(Status) WriteGlobalOptions();
  744.                     break;
  745.  
  746.                 case SLOT_SPECIAL_MAIL:
  747.                     Status = DialogBox(gOptions.hAppInst, "MAILOPTIONSDLG", hwnd, lpfnMailOptionsDlgProc);
  748.                     if(Status) WriteGlobalOptions();
  749.                     break;
  750.  
  751.                 case SLOT_SPECIAL_CLOCK:
  752.                     Status = DialogBox(gOptions.hAppInst, "CLOCKOPTIONSDLG", hwnd, lpfnClockOptionsDlgProc);
  753.                     if(Status) WriteGlobalOptions();
  754.                     break;
  755.             }
  756.  
  757.             return 0;
  758.  
  759.  
  760.         case WM_CLOSE:
  761.             DestroyWindow(hwnd);
  762.             return 0;
  763.  
  764.         case WM_QUIT:
  765.         case WM_DESTROY:
  766.             FreeProcInstance(lpfnAppOptionsDlgProc);
  767.             FreeProcInstance(lpfnAboutDockDlgProc);
  768.             FreeProcInstance(lpfnWinExitOptionsDlgProc);
  769.             FreeProcInstance(lpfnMailOptionsDlgProc);
  770.             FreeProcInstance(lpfnMainOptionsDlgProc);
  771.             FreeProcInstance(lpfnClockOptionsDlgProc);
  772.             KillTimer(Dock.hwndDock, MAIL_TIMER);
  773.             /**************************************
  774.                 Release all the Device Contexts
  775.                 and bitmaps used
  776.             **************************************/
  777.             SelectObject(Dock.hdcIconCache, hbmOldIconCache);
  778.             SelectObject(hdcUnderIcon,      hbmOldUnderIcon);
  779.             SelectObject(hdcNewUnderIcon,   hbmOldNewUnderIcon);
  780.             SelectObject(hdcTmp,            hbmOldTmp);
  781.  
  782.             Status = 0;
  783.             
  784.             Status += DeleteObject(hbmUnderIcon);
  785.             Status += DeleteObject(hbmNewUnderIcon);
  786.             Status += DeleteObject(hbmTmp);
  787.             Status += DeleteObject(Dock.hbmIconCache);
  788.             Status += DeleteDC(hdcUnderIcon);
  789.             Status += DeleteDC(hdcNewUnderIcon);
  790.             Status += DeleteDC(hdcTmp);
  791.             Status += DeleteDC(Dock.hdcIconCache);
  792.  
  793.             DestroyCursor(hCurHand);
  794.             // Delete UtilLoadIcon() internal bitmap handle.
  795.             UtilLoadIcon( NULL, NULL );
  796.  
  797.             if( Status != 0 ){
  798.                   MessageBox(hwnd, "Error releasing Resources, you may need to restart Windows.", 
  799.                              "FreeDock Resource Error", MB_OK | MB_ICONSTOP);
  800.             }    
  801.  
  802.             free(Slot);
  803.             PostQuitMessage(0);
  804.             return 0;
  805.     }
  806.  
  807.     /* return all unused mesages to the system */
  808.     return DefWindowProc(hwnd, message, wParam, lParam);
  809. }
  810.